home *** CD-ROM | disk | FTP | other *** search
- /*
- * @(#)buildGraphs.c 1.3 6/29/87
- */
- #include "assert.h"
- #include "nodes.h"
- #include "map.h"
- #include "sequence.h"
- #include "trace.h"
-
- Map symbolsRead;
- Map symbolsWritten;
-
- void addAnEdge(map, symref, expression)
- Map map;
- NodePtr symref, expression;
- {
- NodePtr list;
- if (symref->b.symref.symbol == NULL) assert(FALSE);
- list = (NodePtr) Map_Lookup(map, (int)symref->b.symref.symbol);
- if ((int)list == NIL) list = NULL;
- Sequence_Add(&list, expression);
- Map_Insert(map, (int)symref->b.symref.symbol, (int)list);
- }
-
- static Boolean duplicatesSymbol(p, st)
- NodePtr p;
- Symbol st;
- {
- NodePtr q;
- switch (p->tag) {
- case P_INVOC:
- Sequence_For(q, p->b.invoc.args)
- assert(q->tag == P_ARG);
- q = q->b.arg.exp;
- if (q->tag == P_SYMREF && q->b.symref.symbol == st) {
- TRACE2(graph, 1, "reference to %s on line %d is as arg, so duplicates",
- ST_SymbolName(st), p->lineNumber);
- return(TRUE);
- }
- Sequence_Next
- TRACE2(graph, 1, "Invocation on %s on line %d does not duplicate",
- ST_SymbolName(st), p->lineNumber);
- break;
- case P_ASSIGNSTAT:
- Sequence_For(q, p->b.assignstat.right)
- if (q->tag == P_SYMREF && q->b.symref.symbol == st) {
- TRACE2(graph, 1, "reference to %s on line %d is as expression, so duplicates",
- ST_SymbolName(st), p->lineNumber);
- return(TRUE);
- }
- Sequence_Next
- TRACE2(graph, 1, "Assignment to %s on line %d does not duplicate",
- ST_SymbolName(st), p->lineNumber);
- break;
- case P_ATLIT:
- case P_OBLIT:
- TRACE2(graph, 1, "reference to %s on line %d is as import, so duplicates",
- ST_SymbolName(st), p->lineNumber);
- return(TRUE);
- /* break; */
- default:
- break;
- }
- return(FALSE);
- }
-
- void buildSymbolGraph(p)
- register NodePtr p;
- {
- register NodePtr q, list;
- Boolean duplicatesSelf;
- register Symbol st;
-
- if ((int)p <= 0x200) return;
- switch (p->tag) {
- case P_ASSIGNSTAT:
- Sequence_For(q, p->b.assignstat.left)
- assert(q->tag == P_SYMREF);
- addAnEdge(symbolsWritten, q, p);
- Sequence_Next
- Sequence_For(q, p->b.assignstat.right)
- if (q->tag == P_SYMREF) addAnEdge(symbolsRead, q, p);
- Sequence_Next
- break;
- case P_INVOC:
- if (p->b.invoc.target->tag == P_SYMREF)
- addAnEdge(symbolsRead, p->b.invoc.target, p);
- Sequence_For(q, p->b.invoc.args)
- assert(q->tag == P_ARG);
- q = q->b.arg.exp;
- if (q->tag == P_SYMREF)
- addAnEdge(symbolsRead, q, p);
- Sequence_Next
- break;
- case P_CONSTDECL:
- case P_VARDECL:
- if (p->b.constdecl.value != NN)
- addAnEdge(symbolsWritten, p->b.constdecl.sym, p);
- break;
- case P_PARAM:
- if (p->b.param.sym->b.symdef.symbol->itsKind == ST_Param)
- addAnEdge(symbolsWritten, p->b.param.sym, p);
- break;
- case P_UNARYEXP:
- if (p->b.unaryexp.exp->tag == P_SYMREF)
- addAnEdge(symbolsWritten, p->b.unaryexp.exp, p);
- break;
- case P_EXP:
- if (p->b.exp.left->tag == P_SYMREF)
- addAnEdge(symbolsWritten, p->b.exp.left, p);
- if (p->b.exp.right->tag == P_SYMREF)
- addAnEdge(symbolsWritten, p->b.exp.right, p);
- break;
- case P_ATLIT:
- case P_OBLIT:
- Sequence_For(q, p->b.oblit.setq)
- if (q->b.setq.outer->tag == P_SYMREF) {
- addAnEdge(symbolsRead, q->b.setq.outer, p);
- }
- assert(q->b.setq.inner->tag == P_SYMDEF);
- addAnEdge(symbolsWritten, q->b.setq.inner, p);
- Sequence_Next
- addAnEdge(symbolsWritten, p->b.atlit.name, p);
- break;
- case P_IMPORT:
- Sequence_For(q, p->b.import.syms)
- addAnEdge(symbolsWritten, q, p);
- Sequence_Next
- break;
- case P_EXPORT:
- if (p->b.export.path == NN) break;
- Sequence_For(q, p->b.export.syms)
- addAnEdge(symbolsWritten, q, p);
- Sequence_Next
- break;
-
- default:
- break;
- }
- Sequence_For(q, p)
- if ((int)q > 0x200) buildSymbolGraph(q);
- Sequence_Next
- switch (p->tag) {
- case P_OBLIT:
- st = p->b.oblit.name->b.symdef.symbol;
- list = (NodePtr) Map_Lookup(symbolsRead, (int)st);
- if ((int)list == NIL) list = NULL;
- duplicatesSelf = FALSE;
- Sequence_For(q, list)
- if (duplicatesSymbol(q, st)) duplicatesSelf = TRUE;
- Sequence_Next
- p->b.oblit.f.doesNotDuplicateSelf = !duplicatesSelf;
- break;
- case P_ATLIT:
- p->b.atlit.f.doesNotDuplicateSelf = TRUE;
- break;
- default:
- break;
- }
- }
-
- void initializeGraphs()
- {
- symbolsRead = Map_Create();
- symbolsWritten = Map_Create();
- }
-
- static void findSingleReferences()
- {
- Symbol st;
- NodePtr list, q;
- Boolean duplicates;
-
- Map_For(symbolsWritten, st, list)
- if (Sequence_Length(list) == 0) {
- TRACE1(graph, 1, "Symbol %s is never written", ST_SymbolName(st));
- } else if (Sequence_Length(list) == 1) {
- TRACE1(graph, 1, "Symbol %s is written only once", ST_SymbolName(st));
- list = (NodePtr) Map_Lookup(symbolsRead, (int)st);
- if (list == (NodePtr)NIL) list = NULL;
- duplicates = FALSE;
- Sequence_For(q, list)
- if (duplicatesSymbol(q, st)) duplicates = TRUE;
- Sequence_Next
- if (!duplicates) {
- TRACE1(graph, 1, "Symbol %s is single reference", ST_SymbolName(st));
- st->isSingleReference = TRUE;
- } else {
- TRACE1(graph, 1, "Symbol %s is not single reference", ST_SymbolName(st));
- }
- } else {
- TRACE2(graph, 1, "Symbol %s is written %d times", ST_SymbolName(st),
- Sequence_Length(list));
- }
- Map_Next
- }
-
- void displaySymbolGraph()
- {
- Symbol st;
- NodePtr list, q;
- IFTRACE(graph, 3) {
- Map_For(symbolsRead, st, list)
- printf("Symbol %s is read:\n", ST_SymbolName(st));
- Sequence_For(q, list)
- printf("\t\tin %s on line %d\n", tagNames[(int)q->tag], q->lineNumber);
- Sequence_Next
- list = (NodePtr) Map_Lookup(symbolsWritten, (int)st);
- if ((int)list != NIL) {
- printf("\tand written:\n");
- Sequence_For(q, list)
- printf("\t\tin %s on line %d\n", tagNames[(int)q->tag], q->lineNumber);
- Sequence_Next
- } else {
- printf("\tbut never written\n");
- }
- Map_Next
- Map_For(symbolsWritten, st, list)
- if (Map_Lookup(symbolsRead, (int)st) == NIL) {
- printf("Symbol %s is only written:\n", ST_SymbolName(st));
- Sequence_For(q, list)
- printf("\t\tin %s on line %d\n", tagNames[(int)q->tag], q->lineNumber);
- Sequence_Next
- }
- Map_Next
- }
- }
-
- void doSymbolGraph(p)
- NodePtr p;
- {
- buildSymbolGraph(p);
- findSingleReferences();
- displaySymbolGraph();
- }
-